﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace JX.Infrastructure.Common
{
	/// <summary>
	/// Lambda表达式转换成SQL语句
	/// </summary>
	public static class LambdaToSqlHelper
	{
		#region 常用方法
		/// <summary>
		/// lambda表达式转换sql，得到where条件语句
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="where"></param>
		/// <param name="listSqlParaModel"></param>
		/// <returns></returns>
		public static string GetWhereSql<T>(this Expression<Func<T, bool>> where, List<SqlParaModel> listSqlParaModel) where T : class
		{
			string result = string.Empty;
			if (where != null)
			{
				Expression exp = where.Body as Expression;
				ConstantExpression ce = exp as ConstantExpression;
				if (ce != null && ce.Value is bool) //表示具有常数值的表达式，并且是布尔类型
				{
					if (ce.Value.ToBoolean())
					{
						return " where 1=1 ";
					}
					else
					{
						return " where 1=2 ";
					}
				}
				result = ExpressionRouter(exp, listSqlParaModel);
			}
			if (result != string.Empty)
			{
				result = " where " + result;
			}
			return result;
		}

		/// <summary>
		/// lambda表达式转换sql，得到order by 语句
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="orderBy"></param>
		/// <returns></returns>
		public static string GetOrderBySql<T>(this Expression<Func<IQueryable<T>, IOrderedQueryable<T>>> orderBy) where T : class
		{
			string result = string.Empty;
			if (orderBy != null && orderBy.Body is MethodCallExpression)
			{
				MethodCallExpression exp = orderBy.Body as MethodCallExpression;
				List<SqlParaModel> listSqlParaModel = new List<SqlParaModel>();
				result = MethodCallExpressionProvider(exp, listSqlParaModel);
			}
			if (result != string.Empty)
			{
				result = " order by " + result;
			}
			return result;
		}

		/// <summary>
		/// lambda表达式转换sql，得到查询字段语句
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <typeparam name="TResult"></typeparam>
		/// <param name="fields"></param>
		/// <returns></returns>
		public static string GetQueryField<T, TResult>(this Expression<Func<T, TResult>> fields)
		{
			StringBuilder sbSelectFields = new StringBuilder();
			if (fields.Body is NewExpression)
			{
				NewExpression ne = fields.Body as NewExpression;
				for (var i = 0; i < ne.Members.Count; i++)
				{
					sbSelectFields.Append(ne.Members[i].Name + ",");
				}
			}
			else if (fields.Body is MemberExpression)
			{
				MemberExpression me = fields.Body as MemberExpression;
				return me.Member.Name;
			}
			else if (fields.Body is ParameterExpression)
			{
				sbSelectFields.Append("*");
			}
			else
			{
				sbSelectFields.Append("*");
			}
			if (sbSelectFields.Length > 1)
			{
				sbSelectFields = sbSelectFields.Remove(sbSelectFields.Length - 1, 1);
			}
			return sbSelectFields.ToString();
		}

		/// <summary>
		/// 对应SQL中的IN语句
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="obj"></param>
		/// <param name="array"></param>
		/// <returns></returns>
		public static bool In<T>(this T obj, T[] array)
		{
			return true;
		}
		/// <summary>
		/// 对应SQL中的 not in 语句
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="obj"></param>
		/// <param name="array"></param>
		/// <returns></returns>
		public static bool NotIn<T>(this T obj, T[] array)
		{
			return true;
		}
		/// <summary>
		/// 对应SQL中的like语句
		/// </summary>
		/// <param name="str"></param>
		/// <param name="likeStr"></param>
		/// <returns></returns>
		public static bool Like(this string str, string likeStr)
		{
			return true;
		}
		/// <summary>
		/// 对应SQL中的 not like 语句
		/// </summary>
		/// <param name="str"></param>
		/// <param name="likeStr"></param>
		/// <returns></returns>
		public static bool NotLike(this string str, string likeStr)
		{
			return true;
		}
		/// <summary>
		/// 对应SQL中的DATEDIFF(datepart,startdate,enddate)函数
		/// </summary>
		/// <param name="startDate"></param>
		/// <param name="endDate"></param>
		/// <param name="interval"></param>
		/// <returns></returns>
		public static int? DateDiff(string interval,DateTime? startDate, DateTime? endDate)
		{
			return null;
		}
		#endregion

		#region 内部方法
		/// <summary>
		/// 路由计算，根据表达式类型来调用对应的处理程序，返回SQL语句，默认返回null。
		/// </summary>
		/// <param name="exp"></param>
		/// <param name="listSqlParaModel"></param>
		/// <returns></returns>
		private static string ExpressionRouter(Expression exp, List<SqlParaModel> listSqlParaModel)
		{
			if (exp is BinaryExpression)    //表示具有二进制运算符的表达式
			{
				return BinarExpressionProvider(exp, listSqlParaModel);
			}
			else if (exp is ConstantExpression) //表示具有常数值的表达式
			{
				return ConstantExpressionProvider(exp, listSqlParaModel);
			}
			else if (exp is LambdaExpression)   //介绍 lambda 表达式。 它捕获一个类似于 .NET 方法主体的代码块
			{
				return LambdaExpressionProvider(exp, listSqlParaModel);
			}
			else if (exp is MemberExpression)   //表示访问字段或属性
			{
				return MemberExpressionProvider(exp, listSqlParaModel);
			}
			else if (exp is MethodCallExpression)   //表示对静态方法或实例方法的调用
			{
				return MethodCallExpressionProvider(exp, listSqlParaModel);
			}
			else if (exp is NewArrayExpression) //表示创建一个新数组，并可能初始化该新数组的元素
			{
				return NewArrayExpressionProvider(exp, listSqlParaModel);
			}
			else if (exp is ParameterExpression)    //表示一个命名的参数表达式。
			{
				return ParameterExpressionProvider(exp, listSqlParaModel);
			}
			else if (exp is UnaryExpression)    //表示具有一元运算符的表达式
			{
				return UnaryExpressionProvider(exp, listSqlParaModel);
			}
			return null;
		}
		/// <summary>
		/// 解析二元表达式
		/// </summary>
		/// <param name="exp"></param>
		/// <param name="listSqlParaModel"></param>
		/// <returns></returns>
		private static string BinarExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
		{
			BinaryExpression be = exp as BinaryExpression;
			Expression left = be.Left;
			Expression right = be.Right;
			ExpressionType type = be.NodeType;
			string sb = "(";
			//先处理左边
			ConstantExpression ce = left as ConstantExpression;
			if (ce != null && ce.Value is bool) //表示具有常数值的表达式，并且是布尔类型
			{
				if (ce.Value.ToBoolean())
				{
					sb += " 1=1 ";
				}
				else
				{
					sb += " 1=2 ";
				}
			}
			else
			{
				sb += ExpressionRouter(left, listSqlParaModel);
			}
			sb += ExpressionTypeCast(type);
			//再处理右边
			string sbTmp = ExpressionRouter(right, listSqlParaModel);
			if (sbTmp == "null")
			{
				if (sb.EndsWith(" = "))
					sb = sb.Substring(0, sb.Length - 2) + " is null";
				else if (sb.EndsWith(" <> "))
					sb = sb.Substring(0, sb.Length - 3) + " is not null";
			}
			else
				sb += sbTmp;
			return sb += ")";
		}
		/// <summary>
		/// 解析常数值的表达式
		/// </summary>
		/// <param name="exp"></param>
		/// <param name="listSqlParaModel"></param>
		/// <returns></returns>
		private static string ConstantExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
		{
			ConstantExpression ce = exp as ConstantExpression;
			if (ce.Value == null)
			{
				return "null";
			}
			else if (ce.Value is ValueType)
			{
				GetSqlParaModel(listSqlParaModel, GetValueType(ce.Value));
				return "@para" + listSqlParaModel.Count;
			}
			else if (ce.Value is string || ce.Value is DateTime || ce.Value is char)
			{
				GetSqlParaModel(listSqlParaModel, GetValueType(ce.Value));
				return "@para" + listSqlParaModel.Count;
			}
			return "";
		}
		/// <summary>
		/// 解析lambda表达式
		/// </summary>
		/// <param name="exp"></param>
		/// <param name="listSqlParaModel"></param>
		/// <returns></returns>
		private static string LambdaExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
		{
			LambdaExpression le = exp as LambdaExpression;
			return ExpressionRouter(le.Body, listSqlParaModel);
		}
		/// <summary>
		/// 解析成员表达式，表示访问字段或属性
		/// </summary>
		/// <param name="exp"></param>
		/// <param name="listSqlParaModel"></param>
		/// <returns></returns>
		private static string MemberExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
		{
			if (!exp.ToString().StartsWith("value"))
			{
				MemberExpression me = exp as MemberExpression;
				if (me.Member.Name == "Now")
				{
					GetSqlParaModel(listSqlParaModel, DateTime.Now);
					return "@para" + listSqlParaModel.Count;
				}
				return me.Member.Name;
			}
			else
			{
				var result = Expression.Lambda(exp).Compile().DynamicInvoke();
				if (result == null)
				{
					return "null";
				}
				else if (result is ValueType)
				{
					GetSqlParaModel(listSqlParaModel, GetValueType(result));
					return "@para" + listSqlParaModel.Count;
				}
				else if (result is string || result is DateTime || result is char)
				{
					GetSqlParaModel(listSqlParaModel, GetValueType(result));
					return "@para" + listSqlParaModel.Count;
				}
				else if (result is int[])
				{
					var rl = result as int[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (int r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r);
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is int?[])
				{
					var rl = result as int?[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (int? r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r.GetValueOrDefault());
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is long[])
				{
					var rl = result as long[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (long r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r);
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is long?[])
				{
					var rl = result as long?[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (long? r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r.GetValueOrDefault());
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is short[])
				{
					var rl = result as short[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (short r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r);
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is short?[])
				{
					var rl = result as short?[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (short? r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r.GetValueOrDefault());
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is decimal[])
				{
					var rl = result as decimal[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (decimal r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r);
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is decimal?[])
				{
					var rl = result as decimal?[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (decimal? r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r.GetValueOrDefault());
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is double[])
				{
					var rl = result as double[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (double r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r);
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is double?[])
				{
					var rl = result as double?[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (double? r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r.GetValueOrDefault());
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is float[])
				{
					var rl = result as float[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (float r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r);
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is float?[])
				{
					var rl = result as float?[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (float? r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r.GetValueOrDefault());
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
				else if (result is string[])
				{
					var rl = result as string[];
					StringBuilder sbTmp = new StringBuilder();
					foreach (var r in rl)
					{
						GetSqlParaModel(listSqlParaModel, r.ToString());
						sbTmp.Append("@para" + listSqlParaModel.Count + ",");
					}
					return sbTmp.ToString().Substring(0, sbTmp.ToString().Length - 1);
				}
			}
			return "";
		}
		/// <summary>
		/// 解析方法表达式，表示对静态方法或实例方法的调用
		/// </summary>
		/// <param name="exp"></param>
		/// <param name="listSqlParaModel"></param>
		/// <returns></returns>
		private static string MethodCallExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
		{
			MethodCallExpression mce = exp as MethodCallExpression;
			if (mce.Method.Name == "Contains")
			{
				if (mce.Object == null)
				{
					return string.Format("{0} in ({1})", ExpressionRouter(mce.Arguments[1], listSqlParaModel), ExpressionRouter(mce.Arguments[0], listSqlParaModel));
				}
				else
				{
					if (mce.Object.NodeType == ExpressionType.MemberAccess)
					{
						//w => w.name.Contains("1")
						var _name = ExpressionRouter(mce.Object, listSqlParaModel);
						var _value = ExpressionRouter(mce.Arguments[0], listSqlParaModel);
						var index = (_value.Length >= 6) ? _value.Substring(5).ToInt32() - 1 : 0;//@para1去掉前面的字符，只保留数字
						listSqlParaModel[index].value = string.Format("%{0}%",listSqlParaModel[index].value);
						return string.Format("{0} like {1}", _name, _value);
					}
				}
			}
			else if (mce.Method.Name == "OrderBy")
			{
				return string.Format("{0} asc", ExpressionRouter(mce.Arguments[1], listSqlParaModel));
			}
			else if (mce.Method.Name == "OrderByDescending")
			{
				return string.Format("{0} desc", ExpressionRouter(mce.Arguments[1], listSqlParaModel));
			}
			else if (mce.Method.Name == "ThenBy")
			{
				return string.Format("{0},{1} asc", MethodCallExpressionProvider(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel));
			}
			else if (mce.Method.Name == "ThenByDescending")
			{
				return string.Format("{0},{1} desc", MethodCallExpressionProvider(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel));
			}
			else if (mce.Method.Name == "Like")
			{
				return string.Format("({0} like {1})", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel).Replace("'", ""));
			}
			else if (mce.Method.Name == "NotLike")
			{
				return string.Format("({0} not like '%{1}%')", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel).Replace("'", ""));
			}
			else if (mce.Method.Name == "In")
			{
				return string.Format("{0} in ({1})", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel));
			}
			else if (mce.Method.Name == "NotIn")
			{
				return string.Format("{0} not in ({1})", ExpressionRouter(mce.Arguments[0], listSqlParaModel), ExpressionRouter(mce.Arguments[1], listSqlParaModel));
			}
			else if (mce.Method.Name == "DateDiff")
			{
				ConstantExpression ce = mce.Arguments[0] as ConstantExpression;
				return string.Format("DateDiff({0},{1},{2})", GetValueType(ce.Value), ExpressionRouter(mce.Arguments[1], listSqlParaModel), ExpressionRouter(mce.Arguments[2], listSqlParaModel));
			}
			else if (mce.Method.Name == "ToBoolean")
			{
				var _value = ExpressionRouter(mce.Arguments[0], listSqlParaModel);
				var index = (_value.Length >= 6) ? _value.Substring(5).ToInt32() - 1 : 0;//@para1去掉前面的字符，只保留数字
				object arg1 = listSqlParaModel[index].value;
				listSqlParaModel.RemoveAt(index);
				return arg1.ToString();
			}
			else if (mce.Method.Name == "ToInt32")
			{
				var _value = ExpressionRouter(mce.Arguments[0], listSqlParaModel);
				var index = (_value.Length >= 6) ? _value.Substring(5).ToInt32() - 1 : 0;//@para1去掉前面的字符，只保留数字
				object arg1 = listSqlParaModel[index].value;
				listSqlParaModel.RemoveAt(index);
				ConstantExpression arg2 = mce.Arguments[1] as ConstantExpression;
				return arg1.ToInt32(arg2.Value.ToInt32()).ToString();
			}
			else if (mce.Method.Name == "ToDecimal")
			{
				var _value = ExpressionRouter(mce.Arguments[0], listSqlParaModel);
				var index = (_value.Length >= 6) ? _value.Substring(5).ToInt32() - 1 : 0;//@para1去掉前面的字符，只保留数字
				object arg1 = listSqlParaModel[index].value;
				listSqlParaModel.RemoveAt(index);
				ConstantExpression arg2 = mce.Arguments[1] as ConstantExpression;
				return arg1.ToDecimal(arg2.Value.ToDecimal()).ToString();
			}
			else if (mce.Method.Name == "ToDouble")
			{
				var _value = ExpressionRouter(mce.Arguments[0], listSqlParaModel);
				var index = (_value.Length >= 6) ? _value.Substring(5).ToInt32() - 1 : 0;//@para1去掉前面的字符，只保留数字
				object arg1 = listSqlParaModel[index].value;
				listSqlParaModel.RemoveAt(index);
				ConstantExpression arg2 = mce.Arguments[1] as ConstantExpression;
				return arg1.ToDouble(arg2.Value.ToDouble()).ToString();
			}
			else if (mce.Method.Name == "ToSingle")
			{
				var _value = ExpressionRouter(mce.Arguments[0], listSqlParaModel);
				var index = (_value.Length >= 6) ? _value.Substring(5).ToInt32() - 1 : 0;//@para1去掉前面的字符，只保留数字
				object arg1 = listSqlParaModel[index].value;
				listSqlParaModel.RemoveAt(index);
				ConstantExpression arg2 = mce.Arguments[1] as ConstantExpression;
				return arg1.ToSingle(arg2.Value.ToSingle()).ToString();
			}
			else if (mce.Method.Name == "ToChar")
			{
				var _value = ExpressionRouter(mce.Arguments[0], listSqlParaModel);
				var index = (_value.Length >= 6) ? _value.Substring(5).ToInt32() - 1 : 0;//@para1去掉前面的字符，只保留数字
				object arg1 = listSqlParaModel[index].value;
				listSqlParaModel.RemoveAt(index);
				return arg1.ToChar().ToString();
			}
			else if (mce.Method.Name == "ToGuid")
			{
				return ExpressionRouter(mce.Arguments[0], listSqlParaModel);
			}
			return "";
		}
		/// <summary>
		/// 解析数组表达式，表示创建一个新数组，并可能初始化该新数组的元素
		/// </summary>
		/// <param name="exp"></param>
		/// <param name="listSqlParaModel"></param>
		/// <returns></returns>
		private static string NewArrayExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
		{
			NewArrayExpression ae = exp as NewArrayExpression;
			StringBuilder sbTmp = new StringBuilder();
			foreach (Expression ex in ae.Expressions)
			{
				sbTmp.Append(ExpressionRouter(ex, listSqlParaModel));
				sbTmp.Append(",");
			}
			return sbTmp.ToString(0, sbTmp.Length - 1);
		}
		/// <summary>
		/// 解析参数表达式，表示一个命名的参数表达式
		/// </summary>
		/// <param name="exp"></param>
		/// <param name="listSqlParaModel"></param>
		/// <returns></returns>
		private static string ParameterExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
		{
			ParameterExpression pe = exp as ParameterExpression;
			return pe.Type.Name;
		}
		/// <summary>
		/// 解析具有一元运算符的表达式
		/// </summary>
		/// <param name="exp"></param>
		/// <param name="listSqlParaModel"></param>
		/// <returns></returns>
		private static string UnaryExpressionProvider(Expression exp, List<SqlParaModel> listSqlParaModel)
		{
			UnaryExpression ue = exp as UnaryExpression;
			var result = ExpressionRouter(ue.Operand, listSqlParaModel);
			ExpressionType type = exp.NodeType;
			if (type == ExpressionType.Not)
			{
				if (result.Contains(" in "))
				{
					result = result.Replace(" in ", " not in ");
				}
				if (result.Contains(" like "))
				{
					result = result.Replace(" like ", " not like ");
				}
			}
			return result;
		}
		/// <summary>
		/// 表达式类型转换，输出“ and ”、“ = ”、“ or ”之类的操作符
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		private static string ExpressionTypeCast(ExpressionType type)
		{
			switch (type)
			{
				case ExpressionType.And:
				case ExpressionType.AndAlso:
					return " and ";
				case ExpressionType.Equal:
					return " = ";
				case ExpressionType.GreaterThan:
					return " > ";
				case ExpressionType.GreaterThanOrEqual:
					return " >= ";
				case ExpressionType.LessThan:
					return " < ";
				case ExpressionType.LessThanOrEqual:
					return " <= ";
				case ExpressionType.NotEqual:
					return " <> ";
				case ExpressionType.Or:
				case ExpressionType.OrElse:
					return " or ";
				case ExpressionType.Add:
				case ExpressionType.AddChecked:
					return " + ";
				case ExpressionType.Subtract:
				case ExpressionType.SubtractChecked:
					return " - ";
				case ExpressionType.Divide:
					return " / ";
				case ExpressionType.Multiply:
				case ExpressionType.MultiplyChecked:
					return " * ";
				default:
					return null;
			}
		}
		/// <summary>
		/// 值类型转换
		/// </summary>
		/// <param name="_value"></param>
		/// <returns></returns>
		private static object GetValueType(object _value)
		{
			var _type = _value.GetType().Name;
			switch (_type)
			{
				case "Decimal": return _value.ToDecimal();
				case "Int32": return _value.ToInt32();
				case "DateTime": return _value.ToDateTime();
				case "String": return _value.ToString();
				case "Char": return _value.ToChar();
				case "Boolean": 
					if (_value.ToBoolean()) return 1; 
					else return 0;
				default: return _value;
			}
		}
		/// <summary>
		/// 把参数值加入sql参数列表中
		/// </summary>
		/// <param name="listSqlParaModel">参数列表</param>
		/// <param name="val">参数值</param>
		private static void GetSqlParaModel(List<SqlParaModel> listSqlParaModel, object val)
		{
			SqlParaModel p = new SqlParaModel();
			p.name = "para" + (listSqlParaModel.Count + 1);
			p.value = val;
			listSqlParaModel.Add(p);
		}
		/// <summary>
		/// 判断表达式类型
		/// </summary>
		/// <param name="exp">lambda表达式</param>
		/// <returns></returns>
		private static EnumNodeType CheckExpressionType(Expression exp)
		{
			switch (exp.NodeType)
			{
				case ExpressionType.AndAlso:
				case ExpressionType.OrElse:
				case ExpressionType.Equal:
				case ExpressionType.GreaterThanOrEqual:
				case ExpressionType.LessThanOrEqual:
				case ExpressionType.GreaterThan:
				case ExpressionType.LessThan:
				case ExpressionType.NotEqual:
					return EnumNodeType.BinaryOperator;
				case ExpressionType.Constant:
					return EnumNodeType.Constant;
				case ExpressionType.MemberAccess:
					return EnumNodeType.MemberAccess;
				case ExpressionType.Call:
					return EnumNodeType.Call;
				case ExpressionType.Not:
				case ExpressionType.Convert:
					return EnumNodeType.UndryOperator;
				default:
					return EnumNodeType.Unknown;
			}
		}
		/// <summary>
		/// NodeType枚举
		/// </summary>
		private enum EnumNodeType
		{
			/// <summary>
			/// 二元运算符
			/// </summary>
			[Description("二元运算符")]
			BinaryOperator = 1,

			/// <summary>
			/// 一元运算符
			/// </summary>
			[Description("一元运算符")]
			UndryOperator = 2,

			/// <summary>
			/// 常量表达式
			/// </summary>
			[Description("常量表达式")]
			Constant = 3,

			/// <summary>
			/// 成员（变量）
			/// </summary>
			[Description("成员（变量）")]
			MemberAccess = 4,

			/// <summary>
			/// 函数
			/// </summary>
			[Description("函数")]
			Call = 5,

			/// <summary>
			/// 未知
			/// </summary>
			[Description("未知")]
			Unknown = -99,

			/// <summary>
			/// 不支持
			/// </summary>
			[Description("不支持")]
			NotSupported = -98
		}
		#endregion
	}

	/// <summary>
	/// Sql参数模型，用于从Lambda表达式转换成SQL语句
	/// </summary>
	public class SqlParaModel
	{
		/// <summary>
		/// 参数名
		/// </summary>
		public string name { set; get; }
		/// <summary>
		/// 参数值
		/// </summary>
		public object value { set; get; }
	}

}
